(ns bing.core
  (:gen-class)
  (:require
   [clojure.string :as ss :refer [starts-with?]]
   [hiccup.core :refer :all]
   [hickory.core :refer [parse as-hickory]]
   [clojure.string :refer [join lower-case split]]
   [clojure.java.shell :refer [sh]]
   [hickory.select :as s]
   [hickory.utils :as u]
   [clojure.java.io :as io]
   [org.httpkit.client :as client]
   [cheshire.core :refer [parse-string]]))

(def bing-url "http://cn.bing.com/")

(def hpimage-url "http://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&nc=time&pid=hp")

(def http-kit-client-options
  {:user-agent "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36"
   :headers {"accept" "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
             "accept-language" "en-us,en;q=0.7,zh-cn;q=0.3"}})

(defn get-filename
  "Get filename with ext from a url"
  [url]
  (second (re-find #".*/(.*\.\w+$?)" url)))

(defn get-image-url
  "Get bing image from bing homepage content"
  [bing-home-body]
  (spit (io/file "t.txt") bing-home-body)
  (or (second  (re-find #"url:'(http://.+?\.jpg)'" bing-home-body))
      (-> (re-find #"url:'(.+?\.jpg)'" bing-home-body)
          second
          (ss/replace "\\" "")
          (subs 1))))

(defn download-img
  "Download this url as image.
  
  img-url can be a full http address:
  `http://.....jpg'
  or a uri:
  `/az/hprichbg/rb/MontBlancVideo_ZH-CN9230432404_1920x1080.jpg'"
  [img-url]
  (let [name (str "./bingbgs/" (get-filename img-url))
        img-url (if (starts-with? img-url "http")
                  img-url
                  (str bing-url (if (starts-with? img-url "/") (subs img-url 1) img-url)))
        outfile (io/file name)]
    (io/make-parents outfile)
    (if-not (.exists outfile)
      (let [in (:body
                @(client/get img-url (assoc http-kit-client-options :as :stream)))]
        (with-open [out (io/output-stream outfile)]
          (io/copy in out)))
      (prn name "exists, skipping ..."))
    outfile))


(defn get-bing-img
  "Dl bing image return the img file "
  []
  (let [resp @(client/get bing-url http-kit-client-options)
        _ (prn (:status resp))
        body (:body resp)
        img-url (get-image-url body)]
    (download-img img-url)))

(defn get-hpimage
  "Get hpimage as well as description. Returns a map with keys :copyright and :descriptions and :url.
   May throw exception for netowrk io or json-parsing error."
  []
  (let [r
        (:body
         @(client/get
           (clojure.string/replace hpimage-url #"time"
                                   (str (System/currentTimeMillis)))
           http-kit-client-options))
        jsmap (parse-string r keyword)]
    {:copyright (get-in jsmap [:images 0 :copyright])
     :descriptions (map :desc (get-in jsmap [:images 0 :hs]))
     :url (get-in jsmap [:images 0 :url])}))


(defn set-as-bg
  "Set this image as background"
  [img]
  (let [rs (sh "feh" "--bg-fill" (.getAbsolutePath img))]
    (prn "Setting bg returns" rs)))




(defn remove-copyright-text
  "Remove copyright logo and author information"
  [s]
  (clojure.string/replace s #"\s+[\(（][@©].+[\)）]" ""))

(defn overlay-text
  "Put text on bing-bg image using output from `get-hpimage`"
  [imgmap]
  (let [title (remove-copyright-text (:copyright imgmap))
        img (download-img (:url imgmap))]
    (sh "./annot.sh" (.getAbsolutePath img) title)
    ;(io/file  "./bingbgs/annot.jpg")
    img
    ))

(defn -main
  [& [with-text?]]
  (try
    (if with-text?
      (try
        (let [imgmap (get-hpimage)]
          (set-as-bg (overlay-text imgmap)))
        (catch Exception e
          (prn "Exception occurs when getting bing-bg by json request, will try with direct parse...")
          (.printStackTrace e)
          (-main)))
      (set-as-bg (get-bing-img)))
    (catch Exception e
      (prn "Get image failed, select random images locally.")
      (set-as-bg (rand-nth (filter #(re-seq #"(?i)\.(jpg|png|jpeg)$" (.getName %)) (file-seq (io/file "./bingbgs/")))))))
  (shutdown-agents) ;; comment this line when developing in REPL
  )

